#include "GLMesh.h"

GLMesh::GLMesh(const std::vector<GLVertex>& vertices,
	const std::vector<unsigned int>& indices)
	: GLDraw(), m_vertices(vertices), m_indices(indices),
	m_diffuseTex(TEXTURE::YELLOW), 
	m_specularTex(TEXTURE::WHITE), 
	m_reflectTex(TEXTURE::BLACK),
	m_reflactTex(TEXTURE::BLACK)
{
	GLProgram* program = GLProgram::ShareProgram();

	program->GenerateArray(m_arrayId);
	program->BindArray(m_arrayId);

	// 载入顶点和索引数据
	glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(GLVertex), &m_vertices[0], GL_STATIC_DRAW);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.size() * sizeof(unsigned int), &m_indices[0], GL_STATIC_DRAW);

	// vertex Positions
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (void*)0);

	// vertex normals
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (void*)offsetof(GLVertex, normal));

	// vertex texture coords
	glEnableVertexAttribArray(2);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), (void*)offsetof(GLVertex, texCoords));
	// offsetof 计算变量偏移地址

	program->UnbindArray();
}

void GLMesh::Draw() const
{
	GLProgram* program = GLProgram::ShareProgram();

	program->ActiveTexture(0);
	program->BindTexture(m_diffuseTex);
	program->SetUniformInt("material.duffuse", 0);

	program->ActiveTexture(1);
	program->BindTexture(m_specularTex);
	program->SetUniformInt("material.specular", 1);

	program->ActiveTexture(2);
	program->BindTexture(m_reflectTex);
	program->SetUniformInt("material.reflect", 2);

	program->ActiveTexture(3);
	program->BindTexture(m_reflactTex);
	program->SetUniformInt("material.reflact", 3);

	// 开始绘制
	program->BindArray(m_arrayId);
	glDrawElements(GL_TRIANGLES, m_indices.size(), GL_UNSIGNED_INT, 0);

	program->UnbindArray();
	program->UnbindTexture();
}

void GLMesh::Draw(int amount) const
{
	GLProgram* program = GLProgram::ShareProgram();

	program->ActiveTexture(0);
	program->BindTexture(m_diffuseTex);
	program->SetUniformInt("material.duffuse", 0);

	program->ActiveTexture(1);
	program->BindTexture(m_specularTex);
	program->SetUniformInt("material.specular", 1);

	program->ActiveTexture(2);
	program->BindTexture(m_reflectTex);
	program->SetUniformInt("material.reflect", 2);

	program->ActiveTexture(3);
	program->BindTexture(m_reflactTex);
	program->SetUniformInt("material.reflact", 3);

	// 开始绘制
	program->BindArray(m_arrayId);
	glDrawElementsInstanced(GL_TRIANGLES, m_indices.size(), GL_UNSIGNED_INT, 0, amount);

	program->UnbindArray();
	program->UnbindTexture();
}

void GLMesh::SetDiffuseTex(unsigned int diffuse)
{
	m_diffuseTex = diffuse;
}

void GLMesh::SetSpecularTex(unsigned int specular)
{
	m_specularTex = specular;
}

void GLMesh::SetReflectTex(unsigned int reflect)
{
	m_reflectTex = reflect;
}

void GLMesh::SetReflactTex(unsigned int reflact)
{
	m_reflactTex = reflact;
}